/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package comunicacao;

import entities.Server;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Level;
import java.util.logging.Logger;
import main.ConfigGeral;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

/**
 *
  * @author Leonardo Lino Nº45340
 * @author Diogo Pires Nº40351
 */
public class GestorZooKeeper {

    private ZooKeeper zk;

    public GestorZooKeeper() {

        org.apache.log4j.BasicConfigurator.configure();

        try {
            connect(ConfigGeral.CG_ZOOKEEP_IP + ":" + ConfigGeral.CG_ZOOKEEP_PORT, 455);

        } catch (IOException ex) {
            System.err.println(ex.toString());
        } catch (InterruptedException ex) {
            System.err.println(ex.toString());
        }
    }

    private ZooKeeper connect(String hosts, int timeout)
            throws IOException, InterruptedException {

        final CountDownLatch signal = new CountDownLatch(1);

        zk = new ZooKeeper(hosts, timeout, null);
        return zk;
    }

    public ArrayList<Server> getAllServers() {
        ArrayList<Server> servers = new ArrayList<>();

        try {

            Stat appNode = zk.exists("/AppServers", null);

            if (appNode != null) {
                ArrayList<Server> serversApp = getChilren("AppServers", Server.TYPE_APP);

                if (serversApp != null) {
                    servers.addAll(serversApp);
                    servers.trimToSize();
                } else {
                    return null;
                }
            }

            ArrayList<Server> serversDB = getChilren("DBServers", Server.TYPE_DB);

            if (serversDB != null) {
                servers.addAll(serversDB);
                servers.trimToSize();
            } else {
                return null;
            }

        } catch (KeeperException ex) {
            Logger.getLogger(GestorZooKeeper.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InterruptedException ex) {
            Logger.getLogger(GestorZooKeeper.class.getName()).log(Level.SEVERE, null, ex);
        }
        return servers;
    }

    private ArrayList<Server> getChilren(String parent, int type) throws KeeperException, InterruptedException {
        ArrayList<Server> servers = new ArrayList<>();

        List<String> children = zk.getChildren("/" + parent, null);

        if (children.size() > 0) {

            for (String str : children) {

                if (str.equals("ID")) {
                    continue;
                }

                Stat stat = zk.exists("/" + parent + "/" + str, null);
                byte[] dataByte = zk.getData("/" + parent + "/" + str, null, stat);
                String dataStr = new String(dataByte);

                Server server = null;
                if (type == Server.TYPE_DB) {
                    String[] piece = dataStr.split(",");

                    String[] primeiro = piece[0].split(":");
                    server = new Server(primeiro[0], Integer.parseInt(primeiro[1]));

                    server.setNodeName(primeiro[2]);

                } else {
                    String[] piece = dataStr.split(":");
                    server = new Server(piece[0], Integer.parseInt(piece[1]));
                    server.setNodeName(str);
                }

                if (type == Server.TYPE_APP) {
                    server.setType(Server.TYPE_APP);
                } else if (type == Server.TYPE_DB) {
                    server.setType(Server.TYPE_DB);
                }
                servers.add(server);
            }
        } else {
            return null;
        }
        servers.trimToSize();
        return servers;
    }

}
